package com.medusa.aps.business.modules.basic.mp.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medusa.aps.business.model.constant.RedisConstants;
import com.medusa.aps.business.model.enums.SourceEnum;
import com.medusa.aps.business.model.pagination.Page;
import com.medusa.aps.business.modules.basic.model.input.WorkshopDTO;
import com.medusa.aps.business.modules.basic.model.input.WorkshopParam;
import com.medusa.aps.business.modules.basic.mp.entity.Workshop;
import com.medusa.aps.business.modules.basic.mp.mapper.WorkshopMapper;
import com.medusa.aps.business.modules.basic.mp.service.WorkshopService;
import com.medusa.aps.business.modules.security.mp.entity.User;
import com.medusa.aps.business.modules.security.mp.service.IUserService;
import com.medusa.aps.business.common.redis.annotation.Redisson;
import com.medusa.aps.business.global.model.exception.GlobalException;
import com.medusa.aps.business.global.model.exception.collector.DistinctValidator;
import com.medusa.aps.business.global.model.exception.collector.ErrorCollector;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author baomidou
 * @since 2023-09-06
 */
@Service
public class WorkshopServiceImpl extends ServiceImpl<WorkshopMapper, Workshop> implements WorkshopService {


    @Resource
    private IUserService userService;
    @Resource
    private WorkshopService workshopService;

    /**
     * 新增车间
     *
     * @param workshops 车间列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @Redisson(name = RedisConstants.WORKSHOP_LOCK_KEY, waitTime = 1)
    public void saveBatchWorkshop(List<WorkshopDTO> workshops) {
        Map<Long, User> userMap = validatorParam(workshops);
        List<Workshop> shops = workshops.stream()
                .map(workshopDTO ->
                        {
                            User user = userMap.get(workshopDTO.getUserId());
                            return new Workshop()
                                    .setWorkshopName(workshopDTO.getWorkshopName())
                                    .setWorkshopCode(workshopDTO.getWorkshopCode())
                                    .setUserId(workshopDTO.getUserId())
                                    .setWorkshopLeader(user.getUsername())
                                    .setContactNumber(user.getPhone())
                                    .setJobNumber(user.getJobNumber())
                                    .setState(workshopDTO.getState())
                                    .setDataSource(SourceEnum.ARTIFICIAL);
                        }
                ).toList();
        //保存操作日志
        boolean success = workshopService.saveBatch(shops);
        if (!success) {
            throw new GlobalException("新增车间失败");
        }
    }

    private Map<Long, User> validatorParam(List<WorkshopDTO> workshops) {
        List<Long> userIds = new ArrayList<>(workshops.size());
        List<String> workshopCodes = new ArrayList<>(workshops.size());
        for (WorkshopDTO workshop : workshops) {
            userIds.add(workshop.getUserId());
            workshopCodes.add(workshop.getWorkshopCode());
        }
        ErrorCollector errorCollector = DistinctValidator.valid(workshops, WorkshopDTO::getWorkshopCode, "车间编码");
        if (errorCollector.hasError()) {
            throw new GlobalException(errorCollector.toString());
        }
        List<User> users = userService.lambdaQuery()
                .select(User::getId, User::getUsername, User::getJobNumber, User::getPhone)
                .in(User::getId, userIds)
                .list();
        if (CollectionUtils.isEmpty(users)) {
            throw new GlobalException("您填写的用户都不存在");
        }
        Set<String> workShopDbs = workshopService.lambdaQuery()
                .select(Workshop::getWorkshopCode)
                .in(Workshop::getWorkshopCode, workshopCodes)
                .list().stream()
                .map(Workshop::getWorkshopCode).collect(Collectors.toSet());
        if (users.size() == new HashSet<>(userIds).size() && CollectionUtils.isEmpty(workShopDbs)) {
            return users.stream().collect(Collectors.toMap(User::getId, user -> user));
        }
        List<Long> userIdDbs = users.stream().map(User::getId).toList();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < workshops.size(); i++) {
            WorkshopDTO workshopDTO = workshops.get(i);
            if (workShopDbs.contains(workshopDTO.getWorkshopCode()) || !userIdDbs.contains(workshopDTO.getUserId())) {
                stringBuilder.append(StrUtil.format("第{}行：", i + 1));
                if (workShopDbs.contains(workshopDTO.getWorkshopCode())) {
                    stringBuilder.append(StrUtil.format("车间编码【{}】系统已存在", workshopDTO.getWorkshopCode()));
                }
                if (!userIdDbs.contains(workshopDTO.getUserId())) {
                    stringBuilder.append("用户id不存在");
                }
                stringBuilder.append(";");
            }
        }
        stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        throw new GlobalException(stringBuilder.toString());
    }

    /**
     * 编辑车间
     *
     * @param workshopDTO 车间DTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @Redisson(name = RedisConstants.WORKSHOP_LOCK_KEY, waitTime = 1)
    public void updateWorkshop(WorkshopDTO workshopDTO) {
        Workshop workshop = workshopService.getById(workshopDTO.getId());
        if (workshop == null) {
            throw new GlobalException("车间不存在");
        }
        //操作日志
        String workshopCode = workshop.getWorkshopCode();
        workshop = new Workshop()
                .setId(workshopDTO.getId())
                .setWorkshopName(workshopDTO.getWorkshopName())
                .setUserId(workshopDTO.getUserId())
                .setState(workshopDTO.getState());
        User user = userService.lambdaQuery()
                .select(User::getId, User::getUsername, User::getPhone, User::getJobNumber)
                .eq(User::getId, workshopDTO.getUserId())
                .one();
        if (user == null) {
            throw new GlobalException("用户不存在");
        }
        workshop.setContactNumber(user.getPhone())
                .setWorkshopLeader(user.getUsername())
                .setWorkshopCode(workshopCode)
                .setJobNumber(user.getJobNumber());
        boolean success = workshopService.updateById(workshop);
        if (!success) {
            throw new GlobalException("更新车间失败");
        }
    }


    /**
     * 分页查询车间
     *
     * @param workshopParam 车间查询参数
     */
    @Override
    public Page<Workshop> pageWorkshop(WorkshopParam workshopParam) {
        return workshopService.lambdaQuery()
                .in(CollUtil.isNotEmpty(workshopParam.getIds()), Workshop::getId, workshopParam.getIds())
                .like(StringUtils.isNotBlank(workshopParam.getWorkshopName()), Workshop::getWorkshopName, workshopParam.getWorkshopName())
                .like(StringUtils.isNotBlank(workshopParam.getWorkshopCode()), Workshop::getWorkshopCode, workshopParam.getWorkshopCode())
                .like(StringUtils.isNotBlank(workshopParam.getWorkshopLeader()), Workshop::getWorkshopLeader, workshopParam.getWorkshopLeader())
                .like(StringUtils.isNotBlank(workshopParam.getContactNumber()), Workshop::getContactNumber, workshopParam.getContactNumber())
                .and(StringUtils.isNotBlank(workshopParam.getKeyword()),
                        wrapper -> wrapper.like(Workshop::getWorkshopName, workshopParam.getKeyword())
                                .or()
                                .like(Workshop::getWorkshopCode, workshopParam.getKeyword())
                )
                .orderByDesc(Workshop::getCreateTime)
                .page(workshopParam);

    }
}
